import Stock from './modules/Stock.js';
import { drawFillText } from './utils/draw.js';
import { calculateFitness, getRandomInt, isCircleColliding, pickOne } from './utils/tool.js';
import Star from './modules/Star.js';
import AI from './modules/AI.js';

let canvas;
let ctx;
let AnimationFrameHandle;

/** 神经网络模型保存和加载路径 */
const savePath = 'indexeddb://stockgame/model';
/** 神经网络模型 */
let model;

window.onload = () => {
    // 加载此文件时，隐藏部分按钮
    ['beignGame'].forEach(item => {
        let ele = document.getElementById(item);
        ele && (ele.style.display = 'none');
    });

    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');

    // 将整个项目的数据都添加都window对象上,这样整个项目都容易获取到
    window.GameData = {
        /** 画布 */
        canvas,
        /** 画笔 */
        ctx,
        /** 怪物的数量 */
        stockArr: [],
        /** 玩家的数量 */
        playerArr: [],
        /** 训练AI时临时暂存的玩家数量 */
        savedPlayerArr: [],
        /** 星星的数量 */
        starArr: [],
        stockCount: 3, // 石头数量
        starCount: 100, // 星星数量
        playerCount: 20, // 玩家数量
        startTime: performance.now(), // 训练AI周期开始的时间
        currentTime: 0, // 训练AI周期正在进行的时间
        epoch: 0, // 迭代次数
    };
};

function mian() {
    // window.GameData.currentTime = performance.now();
    // const timeDifference = window.GameData.currentTime - window.GameData.startTime;
    if (window.GameData.playerArr.length === 0) {
        // if (timeDifference >= 0.1 * 60 * 1000) {

        // 按照生存时间和分数进行排序，生存时间优先级更高
        // window.GameData.savedPlayerArr.sort((a, b) => {
        //     if (b.score !== a.score) {
        //         // 如果生存时间不同，按生存时间降序排列
        //         return b.score - a.score;
        //     } else {
        //         // 否则按照分数降序排列
        //         return b.liveTime - a.liveTime;
        //     }
        // });
        // let bestPlayer = window.GameData.savedPlayerArr[0];
        // // 生成新的玩家
        // let tempArr = [];
        // for (let i = 0; i < window.GameData.playerCount; i++) {
        //     let newPlayer = new AI(ctx, getRandomInt(50, canvas.width - 50), getRandomInt(50, canvas.height - 50), bestPlayer.brain);
        //     newPlayer.mutate();
        //     tempArr.push(newPlayer);
        // }

        // 清理tensorflow的内存
        // for (const savedPlayer of window.GameData.savedPlayerArr) {
        //     savedPlayer.dispose();
        // }
        // console.log('生成下一代，最高分为' + bestPlayer.score, '存活时间为：' + bestPlayer.liveTime);

        calculateFitness(window.GameData.savedPlayerArr);
        let tempArr = [];
        for (let i = 0; i < window.GameData.playerCount; i++) {
            tempArr[i] = pickOne(window.GameData.savedPlayerArr, ctx);
        }
        for (let i = 0; i < window.GameData.playerCount; i++) {
            window.GameData.savedPlayerArr[i].dispose();
        }
        window.GameData.savedPlayerArr = [];

        // 赋值新的玩家
        window.GameData.playerArr = tempArr;

        // 刷新计时器
        // window.GameData.startTime = performance.now();
        window.GameData.epoch++;
    }
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // 绘制对象
    for (const stock of window.GameData.stockArr) {
        stock.update();
        stock.draw();
    }
    for (const player of window.GameData.playerArr) {
        player.update();
        player.draw();
    }
    for (const star of window.GameData.starArr) {
        star.update();
        star.draw();
    }

    // 玩家与石头或星星相撞，则淘汰玩家（一个玩家时，直接结束游戏）
    for (const stock of window.GameData.stockArr) {
        for (const player of window.GameData.playerArr) {
            if (isCircleColliding(stock, player)) {
                window.GameData.savedPlayerArr.push(player);
                let index = window.GameData.playerArr.findIndex(item => item.id === player.id);
                window.GameData.playerArr.splice(index, 1);
            }
        }
    }

    // 如果玩家和星星相撞，则给玩家加分
    for (const star of window.GameData.starArr) {
        for (const player of window.GameData.playerArr) {
            if (isCircleColliding(star, player)) {
                player.score++;
                let index = window.GameData.starArr.findIndex(item => item.id === star.id);
                window.GameData.starArr.splice(index, 1);
            }
        }
    }

    // 如果星星数量不足的话，则不足星星数量
    if (window.GameData.starArr.length < window.GameData.starCount) {
        let diff = window.GameData.starCount - window.GameData.starArr.length;
        for (let i = 0; i < diff; i++) {
            window.GameData.starArr.push(new Star(ctx, getRandomInt(50, canvas.width - 50), getRandomInt(50, canvas.height - 50)));
        }
    }

    // if (window.GameData.playerArr.length !== 0) {
    //     // 更新UI
    //     drawFillText(ctx, 20, 20, `玩家0分数：${window.GameData.playerArr[0].score}`, 'red');
    // }

    drawFillText(ctx, canvas.width / 2 - 80, 40, `迭代次数${window.GameData.epoch}`, 'red', 30);

    AnimationFrameHandle = requestAnimationFrame(mian);
}

/** 初始化游戏数据 */
function initGameData() {
    window.GameData.stockArr = [];
    window.GameData.playerArr = [];
    window.GameData.starArr = [];
    window.GameData.savedPlayerArr = [];
    window.GameData.startTime = performance.now();
    window.GameData.epoch = 0;

    const unMoveAbleArr = [
        { x: 30, y: 30 },
        { x: canvas.width - 30, y: 30 },
        { x: 30, y: canvas.height - 30 },
        { x: canvas.width - 30, y: canvas.height - 30 },

        { x: 30, y: canvas.height / 2 },
        { x: canvas.width / 2, y: 30 },
        { x: canvas.width - 30, y: canvas.height / 2 },
        { x: canvas.width / 2, y: canvas.height - 30 },
    ];

    // 生成对象
    // 生成可移动石头
    for (let i = 0; i < window.GameData.stockCount; i++) {
        window.GameData.stockArr.push(new Stock(ctx, getRandomInt(50, canvas.width - 50), getRandomInt(50, canvas.height - 50)));
    }
    // 不可移动的石头
    for (let i = 0; i < unMoveAbleArr.length; i++) {
        let config = unMoveAbleArr[i];
        window.GameData.stockArr.push(new Stock(ctx, config.x, config.y, null, null, 30, 'red', false));
    }

    for (let i = 0; i < window.GameData.playerCount; i++) {
        window.GameData.playerArr.push(new AI(ctx, getRandomInt(50, canvas.width - 50), getRandomInt(50, canvas.height - 50)));
    }
    for (let i = 0; i < window.GameData.starCount; i++) {
        window.GameData.starArr.push(new Star(ctx, getRandomInt(50, canvas.width - 50), getRandomInt(50, canvas.height - 50)));
    }
}

/** 开始游戏 */
function startGame() {
    cancelAnimationFrame(AnimationFrameHandle);
    initGameData();
    mian();
}

document.getElementById('loadAI').addEventListener('click', async () => {
    // 加载模型
    const modelsInfo = await tf.io.listModels();
    if (!modelsInfo[savePath]) {
        console.log('本地未保存模型');
        return;
    }
    model = await tf.loadLayersModel(savePath);
});

document.getElementById('trainAI').addEventListener('click', () => {
    console.log(`将生成${window.GameData.playerCount}个AI参与训练`);
    startGame();
});

document.getElementById('AIPlay').addEventListener('click', () => {});
